package cn.huaqingcheng.tool.crypto.digest;

import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

interface DigestTool {

    static byte[] digest(DigestAlgorithm algorithm, byte[] input) {
        return digest(algorithm.getAlgorithm(), input);
    }

    /**
     * 计算摘要
     *
     * @param algorithm 使用的摘要算法 {@link DigestAlgorithm}
     * @param input     需要计算的数据
     */
    static byte[] digest(String algorithm, byte[] input) {
        try {
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            digest.update(input);
            return digest.digest();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    static byte[] digest(DigestAlgorithm algorithm, InputStream is) {
        return digest(algorithm.getAlgorithm(), is);
    }

    /**
     * 计算一个字节流, 使用 1M 缓冲区
     *
     * @param algorithm 使用的摘要算法  {@link DigestAlgorithm}
     * @param is        输入流, 执行完会关闭输入流
     */
    @SuppressWarnings("MagicNumber")
    static byte[] digest(String algorithm, InputStream is) {
        return digest(algorithm, is, 1024 * 1024);
    }

    /**
     * 计算一个字节流
     *
     * @param algorithm 使用的摘要算法  {@link DigestAlgorithm}
     * @param is        输入流, 执行完会关闭输入流
     * @param len       每次读取的字节数组大小 (缓冲区)
     */
    static byte[] digest(String algorithm, InputStream is, int len) {
        try (is) {
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            while (true) {
                byte[] bytes = is.readNBytes(len);
                if (bytes.length == 0) {
                    break;
                }
                digest.update(bytes);
            }
            return digest.digest();
        } catch (NoSuchAlgorithmException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    static byte[] digest(DigestAlgorithm algorithm, InputStream is, int len) {
        return digest(algorithm.getAlgorithm(), is, len);
    }

}
